﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace IgnData
{
    public static class MapFactory
    {
        /// <summary>
        /// Crea un mapa del tamaño indicado en px
        /// Centrado en el punto que se pasa.
        /// </summary>
        public static IgnMap GetMapByPxSize(GeoCoord utmCoord, int pxSize)
        {
            GeoCoord tp = IgnConverter.UtmToTile(utmCoord);
            int numTiles = (int)Math.Ceiling(((double)pxSize) / 256.0);
            int tileRad = (numTiles / 2) + 1;
            numTiles += 2;
            GeoCoord refTilePoint = new GeoCoord(tp.X - tileRad, tp.Y + tileRad);
            GeoCoord pxPoint = IgnConverter.UtmToPx(utmCoord);
            GeoCoord pxRefPoint = IgnConverter.TileToPx(refTilePoint);
            GeoCoord utmRefPoint = IgnConverter.PxToUtm(pxRefPoint);



            int dX = (int)(pxPoint.X - pxRefPoint.X);
            int dy = (int)(pxRefPoint.Y - pxPoint.Y);
            Bitmap mapaGrande = new Bitmap(numTiles * 256, numTiles * 256);
            using (Graphics mapGrph = Graphics.FromImage(mapaGrande))
            {
                mapGrph.FillRectangle(new SolidBrush(Color.Coral), 0, 0, mapaGrande.Height, mapaGrande.Width);
                for (int di = 0; di < numTiles; di++)
                {
                    for (int dj = 0; dj < numTiles; dj++)
                    {
                        Tile tile = TileManager.GetTile((int)refTilePoint.X + di, (int)refTilePoint.Y - dj);
                        mapGrph.DrawImage(tile.Bmp, di * 256, dj * 256);
                    }
                }


                Pen pen = new Pen(Color.DeepPink, 2);
                mapGrph.DrawArc(pen, dX - 4, dy - 4, 8, 8, 0, 360);
            }

            Bitmap mapaPequeño = new Bitmap(pxSize, pxSize);
            using (Graphics mpGr = Graphics.FromImage(mapaPequeño))
            {
                mpGr.FillRectangle(new SolidBrush(Color.Chartreuse), 0, 0, mapaGrande.Height, mapaGrande.Width);
                Rectangle clipRect = new Rectangle(dX - pxSize / 2, dy - pxSize / 2, pxSize, pxSize);
                mpGr.DrawImage(mapaGrande, 0, 0, clipRect, GraphicsUnit.Pixel);
            }

            IgnMap map = new IgnMap();

            map.Bmp = mapaPequeño;
            GeoRef gr = new GeoRef();
            gr.X = utmCoord.X;
            gr.Y = utmCoord.Y;
            map.Georeference = gr;

            return map;
        }

        /// <summary>
        /// Crea un mapa del tamaño indicado en tiles
        /// Centrado en el punto que se pasa.
        /// </summary>
        public static IgnMap GetMapByTileSize(GeoCoord centralUtmCoord, int tileSize)
        {
            //Coordenadas de referencia
            GeoCoord centralTile;
            GeoCoord upperLeftTile;
            GeoCoord upperLeftUtm;

            centralTile = IgnConverter.UtmToTile(centralUtmCoord);
            

            //Calculo del tile de la esquina superior izquierda
            upperLeftTile = new GeoCoord();
            if (tileSize % 2 == 1) //impar
            {
                int d = tileSize / 2;
                upperLeftTile.X = centralTile.X - d;
                upperLeftTile.Y = centralTile.Y + d;
            }
            else //Pares
            {
                GeoCoord centralPx = IgnConverter.UtmToPx(centralUtmCoord);
                GeoCoord upperLeftCentralTilePx = IgnConverter.TileToPx(centralTile);
                double dx = centralPx.X - upperLeftCentralTilePx.X;
                double dy = upperLeftCentralTilePx.Y - centralPx.Y;
                //2 tiles
                if (dx < 128 && dy < 128)
                {
                    upperLeftTile.X = centralTile.X - 1;
                    upperLeftTile.Y = centralTile.Y + 1;
                }
                else if (dx >= 128 && dy < 128)
                {
                    upperLeftTile.X = centralTile.X;
                    upperLeftTile.Y = centralTile.Y + 1;
                }
                else if (dx >= 128 && dy >= 128)
                {
                    upperLeftTile.X = centralTile.X;
                    upperLeftTile.Y = centralTile.Y;
                }
                else
                {
                    upperLeftTile.X = centralTile.X - 1;
                    upperLeftTile.Y = centralTile.Y;
                }
                //mas de 2 tiles
                int d = (tileSize - 2) / 2;
                if (d > 0)
                {
                    upperLeftTile.X = upperLeftTile.X - d;
                    upperLeftTile.Y = upperLeftTile.Y + d;
                }
            }

            

            Bitmap mapImg = new Bitmap(tileSize * 256, tileSize * 256);
            using (Graphics mapGrph = Graphics.FromImage(mapImg))
            {
                mapGrph.FillRectangle(new SolidBrush(Color.Coral), 0, 0, mapImg.Height, mapImg.Width);
                for (int di = 0; di < tileSize; di++)
                {
                    for (int dj = 0; dj < tileSize; dj++)
                    {
                        Tile tile = TileManager.GetTile(upperLeftTile.X + di, upperLeftTile.Y - dj);
                        mapGrph.DrawImage(tile.Bmp, di * 256, dj * 256);
                    }
                }
            }


            IgnMap map = new IgnMap();
            map.Bmp = mapImg;

            upperLeftUtm = IgnConverter.PxToUtm(IgnConverter.TileToPx(upperLeftTile));
            GeoRef gr = new GeoRef();
            gr.X = upperLeftUtm.X;
            gr.Y = upperLeftUtm.Y;
            gr.ScaleX = 4;
            gr.ScaleY = 4;
            map.Georeference = gr;
            return map;
        }
    }
}
